#ifndef _MEMALLOC_IMPL_H
#define _MEMALLOC_IMPL_H

#include <string>
#include <unordered_set>
#include <vector>
#include "memalloc.hpp"
#include "istorage.h"


class MemAllocImpl {
	friend class MemAlloc;
	template <class T>
	friend class SmartPtr;
	private:

	MemAllocImpl(uint64_t mem_size, uint64_t swap_size,
	    const std::string& swap_path);
	~MemAllocImpl();

	SmartPtrImpl *Alloc(uint64_t size);
	void Free(SmartPtrImpl *ptr); 

	void AddRef(SmartPtrImpl *ptr);
	void DelRef(SmartPtrImpl *ptr);

	void *Lock(SmartPtrImpl *ptr);
	void Release(SmartPtrImpl *ptr);

	void MoveChunkFromMemToSwap(StorageChunk** to_move_chunk);
	void MoveChunkFromSwapToMem(StorageChunk** to_move_chunk);

	void CopyChunkFromMemToSwap(StorageChunk** to_move_chunk);
	void CopyChunkFromSwapToMem(StorageChunk** to_move_chunk);

	void AssertOk();
	
	IStorage *pmem_;
	IStorage *pswap_;

	std::list<StorageChunk**> may_be_freed_;
	std::list<StorageChunk**> may_be_unswapped_;

	std::unordered_set<SmartPtrImpl*> allocated_;
};

class SmartPtrImpl {
	friend class MemAllocImpl;
	private:

	SmartPtrImpl(uint64_t size,
	    const std::list<StorageChunk**>::iterator& imay_be_freed,
	    const std::list<StorageChunk**>::iterator& imay_be_unswapped);
	
	uint64_t size_;

	uint64_t ref_counter_;
	uint64_t lock_counter_;

	StorageChunk *pswap_chunk_;
	StorageChunk *pmem_chunk_;

	std::list<StorageChunk**>::iterator imay_be_freed_;
	std::list<StorageChunk**>::iterator imay_be_unswapped_;
	
};

#endif // _MEMALLOC_IMPL_H

